package org.store.dao;

import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.transaction.annotation.Transactional;
import org.store.domain.Address;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

public class AddressDao extends AbstractDao<Address> {

    @Override
    public Address getById(long id) throws DaoException {
        try {
            return jdbcTemplate.queryForObject("select address_id, street1, street2, city, country, zipCode, phone from address where address_id = ?", MAPPER, id);
        } catch (DataAccessException e) {
            throw new DaoException("Cannot get address with id = " + id, e);
        }
    }

    @Override
    @Transactional
    public Address save(Address address) throws DaoException {
        if (address == null)
            throw new IllegalArgumentException("Address cannot be null");
        try {
            long id = jdbcTemplate.queryForLong("insert into address (street1, street2, city, country, zipCode, phone) values (?,?,?,?,?,?) returning address_id",
                    address.getStreet1(),
                    address.getStreet2(),
                    address.getCity(),
                    address.getCounty(),
                    address.getZipCode(),
                    address.getPhone()
            );
            address.setId(id);
            return address;
        } catch (DataAccessException e) {
            throw new DaoException("Cannot save address with id = " + address.getId(), e);
        }
    }

    @Override
    public boolean delete(Address address) throws DaoException {
        try {
            int updated = jdbcTemplate.update("delete from address where address_id = ?", address.getId());
            return updated > 0;
        } catch (DataAccessException e) {
            throw new DaoException("Cannot delete address with id = " + address.getId(), e);
        }
    }

    @Override
    public Address saveOrUpdate(Address address) throws DaoException {
        if (address.getId() == null) {
            return save(address);
        }
        try {
            jdbcTemplate.update("update address SET street1 = ?, street2 = ?, city = ?, country = ?," +
                    " zipCode = ?, phone = ? where address_id = ?", address.getStreet1(),
                    address.getStreet2(), address.getCity(), address.getCounty(), address.getZipCode(),
                    address.getPhone(), address.getId());
            return address;
        } catch (DataAccessException e) {
            throw new DaoException("Cannot update address with id = " + address.getId(), e);
        }
    }

    @Override
    @Transactional
    public List<Address> saveAll(List<Address> addresses) throws DaoException {
        if (addresses == null)
            throw new IllegalArgumentException("Array cannot be null");
        for (Address address : addresses) {
            save(address);
        }
        return addresses;
    }

    @Override
    public boolean isExists(long id) throws DaoException {
        try {
            return jdbcTemplate.queryForLong("select count(*) from address where address_id = ?", id) > 0;
        } catch (DataAccessException e) {
            throw new DaoException("Cannot get address with id = " + id, e);
        }

    }

    private static final RowMapper<Address> MAPPER = new RowMapper<Address>() {
        @Override
        public Address mapRow(ResultSet rs, int rowNum) throws SQLException {
            Address address = new Address(
                    rs.getString("street1"),
                    rs.getString("street2"),
                    rs.getString("city"),
                    rs.getString("country"),
                    rs.getString("zipCode"),
                    rs.getString("phone")
            );
            address.setId(rs.getLong("address_id"));
            return address;
        }
    };
}
